package com.cloud.security.jwt;

import cn.hutool.json.JSONUtil;
import com.cloud.pojo.user.UserInfo;
import com.cloud.service.LoginService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 本项目未使用JWT
 * JWT权限控制流程: 登录完后创建token返回给前端, 前端每次请求都携带此token, 然后在JWT过滤器中验证token的有效性
 */
@Component
public class JWTProvider {

    private Key key;    // 私钥
    private long tokenValidityInMilliseconds; // token有效时间

    @Resource
    private JwtProperties jjwtProperties; // jwt配置参数

    @Resource
    private LoginService loginService;

    @PostConstruct
    public void init() {
        this.key = Keys.hmacShaKeyFor(jjwtProperties.getKey().getBytes(StandardCharsets.UTF_8)); // 使用mac-sha算法的密钥
        this.tokenValidityInMilliseconds = 1000 * jjwtProperties.getTokenExpiredTime();
    }

    public String createToken(Authentication authentication) {
        long now = (new Date()).getTime();
        Date validity;
        validity = new Date(now + this.tokenValidityInMilliseconds);
        UserInfo user = loginService.findUserByUsername(authentication.getName());
        Map<String, Object> map = new HashMap<>();
        map.put("sub", authentication.getName());
        map.put("user", user);
        return Jwts.builder()
                .setClaims(map) // 添加body
                .signWith(key, SignatureAlgorithm.HS256) // 指定摘要算法
                .setExpiration(validity) // 设置有效时间
                .compact();
    }

    public Authentication getAuthentication(String token) {
        Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token).getBody(); // 根据token获取body
        Object user = claims.get("user");
        String userInfoJson = JSONUtil.toJsonStr(user);
        UserInfo userInfo = JSONUtil.toBean(userInfoJson, UserInfo.class);
        return new UsernamePasswordAuthenticationToken(userInfo, token, userInfo.getAuthorities());
    }
}
